import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;

import javax.media.opengl.GL;
import javax.media.opengl.GLException;

import com.sun.opengl.util.texture.Texture;
import com.sun.opengl.util.texture.TextureIO;

// class Portal defines the state and drawing of the portals
public class Portal {

	private Point3D gate1;
	private Point3D gate2;
	private Point3D gate1Normal= new Point3D();
	private Point3D gate2Normal= new Point3D();
	private int gate1Idx;
	private int gate2Idx;
	private int gate1wall;
	private int gate2wall;
	
	static GLModel gate1obj;
	static GLModel gate2obj;
	
	public void restartPortal(){
		gate1= null;
		gate2= null;
		gate1Normal= new Point3D();
		gate2Normal= new Point3D();
		gate1wall=0;
		gate2wall=0;
	}
	
	
	public void openPortal(int gate, Point3D org2, int wall) {
		
		switch (gate) {
		case 1:
			gate1= org2;
			gate1wall=wall;
			break;
		case 2:
			gate2= org2;
			gate2wall=wall;
			break;

		default:
			break;
		}
		
		
	}
	
	public void  buildPortal(GL gl){
		// create gate1 and gate2 models from obj files
		gate1obj = init_object(gl, "portal.obj", "benchTop.jpg", ".jpg");
		gate2obj = init_object(gl, "portal.obj", "wood.jpg", ".jpg");	
		gate1Idx = gl.glGenLists(1);
		buildGate(gl, gate1Idx, gate1obj);
		gate2Idx = gl.glGenLists(1);
		buildGate(gl, gate2Idx, gate2obj);


			
	}
	
	
	public void buildGate(GL gl, int idx, GLModel obj){
//		gate1obj = init_object(gl, "portal.obj", "benchTop.jpg", ".jpg");
//		gate2obj = init_object(gl, "portal.obj", "wood.jpg", ".jpg");
		
		gl.glNewList(idx, GL.GL_COMPILE);


		//gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
        //gl.glLoadIdentity();  // Reset The View
		gl.glPushMatrix();
        gl.glTranslatef(0.0f, 0.0f, 0.0f);
        gl.glScalef(100f, 180f, 180f);
        
		obj.opengldraw(gl);
		
		
		gl.glPopMatrix();
		

		
		gl.glEndList();
	}
	public void draw(GL gl){
		if (gate1!=null){
			drawBySide(gl,gate1,gate1Normal,gate1wall,gate1Idx);
		
		}
		if (gate2!=null){
			drawBySide(gl,gate2,gate2Normal,gate2wall,gate2Idx);

		}
	}
	
	
	private void drawBySide(GL gl,Point3D gate,Point3D normal, int gatewal,int gateIdx) {
		
		gl.glPushMatrix();
		//rotat according to the wall

		switch (gatewal) {
		case 1:
			//forward
			gl.glTranslated(gate.x,gate.y,gate.z-5  );
			gl.glRotatef(90,0.0f, -1.0f,0.0f);
			normal.x = 0;
			normal.y = 0;
			normal.z = -1;
			break;
		case 2:
			//back
			gl.glTranslated(gate.x,gate.y,gate.z+5  );
			gl.glRotatef(90,0.0f, 1.0f,0.0f);
			normal.x = 0;
			normal.y = 0;
			normal.z = 1;
			break;
		case 3:
			//right
			gl.glTranslated(gate.x+2,gate.y,gate.z );
			gl.glRotatef(90,1.0f, 0.0f,0.0f);
			normal.x = 1;
			normal.y = 0;
			normal.z = 0;
			break;
		case 4:
			//left
			gl.glTranslated(gate.x-2,gate.y,gate.z );
			gl.glRotatef(90,-1.0f, 0.0f,0.0f);
			normal.x = -1;
			normal.y = 0;
			normal.z = 0;
			break;
		case 5:
			gl.glTranslated(gate.x,gate.y+10,gate.z-5  );
			gl.glRotatef(90,0.0f, 0.0f,-1.0f);
			normal.x = 0;
			normal.y = -1;
			normal.z = 0;
			break;
		case 6:
			//celling
			gl.glTranslated(gate.x,gate.y-5,gate.z-5  );
			gl.glRotatef(90,0.0f, 0.0f,1.0f);
			normal.x = 0;
			normal.y = 1;
			normal.z = 0;
			break;


		}

		gl.glCallList(gateIdx);
		gl.glPopMatrix();
		
	}
	public Point3D[] checkPortalEnterance(Point3D location) {
		if (gate1!=null ){
			 
			
			if ((location.x <= gate1.x+120 && location.x >= gate1.x-120) &&
				(location.y <= gate1.y+200 && location.y >= gate1.y-200) &&
				(location.z <= gate1.z+120 && location.z >= gate1.z-120)){
				
				if (gate2!=null)
					return createWrapPoint(gate2, gate2Normal ,gate1Normal, gate2wall);

			
			}
			

		}
		if (gate2!=null ){
			if ((location.x <= gate2.x+120 && location.x >= gate2.x-120) &&
				(location.y <= gate2.y+200 && location.y >= gate2.y-200) &&
				(location.z <= gate2.z+120 && location.z >= gate2.z-120)){
				
				if (gate1!=null)
					return createWrapPoint(gate1, gate1Normal,gate2Normal, gate1wall);
			
			}
			

		} 
		return null;
		
	}
	private Point3D[] createWrapPoint(Point3D gate,Point3D normal,Point3D secNoraml,int gatewall){
		
		
		Point3D[] p = new Point3D[3];
		
		switch (gatewall) {
		case 1:
			//forward
			p[0]= new Point3D(gate.x,gate.y,gate.z-200);
			break;
		case 2:
			//back
			p[0]= new Point3D(gate.x,gate.y,gate.z+200);
			break;
		case 3:
			//right
			p[0]= new Point3D(gate.x+200,gate.y,gate.z);

			break;
		case 4:
			//left
			p[0]= new Point3D(gate.x-200,gate.y,gate.z);

			break;
		case 5:
			//floor
			p[0]= new Point3D(gate.x,gate.y+200,gate.z);
			
			break;
		case 6:
			//celling
			p[0]= new Point3D(gate.x,gate.y-200,gate.z);
			break;


		}
		
		
		//p[0]= new Point3D(gate2.x,gate2.y,gate2.z-120);
		
		p[1]= normal;
		p[2]=secNoraml;
		return p;
	}

	// init_object() load obj file and texture file to a GLModel object 
	public GLModel init_object(GL gl, String obj_filename, String tex_filename, String tex_filetype) {
//    	String obj_filename = "portal.obj";
//    	String tex_filename = "Picture1.jpg";
//    	String tex_filetype = ".jpg";
	 	Texture texture=null;
	 	
//	 	wobject = new WavefrontObjectLoader_DisplayList(obj_filename);
    	
    	//Loading texture init gl model
    	File file = new File(obj_filename);
    	try {
    			
    			BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
    			
    			if(tex_filename!=null)
    			{
	    			texture = TextureIO.newTexture(this.getClass().getResource(tex_filename), true, tex_filetype);
	    			return new GLModel(br, false, gl, texture);
    			}
    			else
    				return new GLModel(br, false, gl, null);
    			

	      } catch (GLException e) {
	         e.printStackTrace();
	      } catch (IOException e) {
	         e.printStackTrace();
	      }
		return null;
    }
}

